import { BookmarkNode, Collection } from '../types/bookmark';

export class BookmarkManager {
  static async getAllBookmarks(): Promise<BookmarkNode[]> {
    return new Promise((resolve) => {
      chrome.bookmarks.getTree((bookmarkTreeNodes) => {
        resolve(this.flattenBookmarkTree(bookmarkTreeNodes));
      });
    });
  }

  static flattenBookmarkTree(nodes: chrome.bookmarks.BookmarkTreeNode[]): BookmarkNode[] {
    const bookmarks: BookmarkNode[] = [];

    const traverse = (node: chrome.bookmarks.BookmarkTreeNode) => {
      // Convert Chrome bookmark node to our BookmarkNode type
      const bookmark: BookmarkNode = {
        id: node.id,
        title: node.title,
        url: node.url,
        parentId: node.parentId,
        dateAdded: node.dateAdded,
      };

      if (node.url) {
        bookmarks.push(bookmark);
      }

      if (node.children) {
        node.children.forEach(traverse);
      }
    };

    nodes.forEach(traverse);
    return bookmarks;
  }

  static async exportToHtml(collection: Collection): Promise<string> {
    const template = `
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>${collection.name}</TITLE>
<H1>${collection.name}</H1>
<DL><p>
    ${collection.bookmarks
      .map(
        (bookmark) => `
    <DT><A HREF="${bookmark.url}" ADD_DATE="${bookmark.dateAdded}">${
          bookmark.title
        }</A></DT>`
      )
      .join('\n')}
</DL><p>`;

    return template;
  }

  static async importFromHtml(html: string): Promise<BookmarkNode[]> {
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');
    const bookmarks: BookmarkNode[] = [];

    const links = doc.getElementsByTagName('a');
    for (let i = 0; i < links.length; i++) {
      const link = links[i];
      const bookmark: BookmarkNode = {
        id: Math.random().toString(36).substr(2, 9),
        title: link.textContent || '',
        url: link.getAttribute('href') || '',
        dateAdded: Number(link.getAttribute('add_date')) || Date.now(),
      };
      bookmarks.push(bookmark);
    }

    return bookmarks;
  }

  static async createBookmark(bookmark: Partial<BookmarkNode>): Promise<BookmarkNode> {
    return new Promise((resolve, reject) => {
      chrome.bookmarks.create(
        {
          parentId: bookmark.parentId,
          title: bookmark.title,
          url: bookmark.url,
        },
        (result) => {
          if (chrome.runtime.lastError) {
            reject(chrome.runtime.lastError);
          } else {
            resolve(result as BookmarkNode);
          }
        }
      );
    });
  }

  static async deleteBookmark(id: string): Promise<void> {
    return new Promise((resolve, reject) => {
      chrome.bookmarks.remove(id, () => {
        if (chrome.runtime.lastError) {
          reject(chrome.runtime.lastError);
        } else {
          resolve();
        }
      });
    });
  }

  static async searchBookmarks(query: string): Promise<BookmarkNode[]> {
    return new Promise((resolve) => {
      chrome.bookmarks.search(query, (results) => {
        resolve(results as BookmarkNode[]);
      });
    });
  }
}
